<template>
  <q-page class="q-pa-md">
    <!-- 查询表单 -->
    <q-card flat bordered class="q-mb-md" v-if="showSearchInput">
      <q-slide-transition>
        <q-card-section>
          <q-form @submit.prevent="handleSearch" class="row q-col-gutter-md">
            <!-- 查询字段 -->
            <q-input
              v-model.trim="searchState.form.username"
              label="用户名"
              outlined
              dense
              clearable
              class="col-md-3 col-sm-6 col-xs-12"
              @keyup.enter="handleSearch"
            >
              <template v-slot:prepend>
                <q-icon name="person" />
              </template>
            </q-input>

            <q-input
              v-model.trim="searchState.form.name"
              label="昵称"
              outlined
              dense
              clearable
              class="col-md-3 col-sm-6 col-xs-12"
              @keyup.enter="handleSearch"
            >
              <template v-slot:prepend>
                <q-icon name="badge" />
              </template>
            </q-input>

            <q-select
              v-model="searchState.form.deptId"
              label="部门"
              :options="deptOptions"
              outlined
              dense
              clearable
              emit-value
              map-options
              class="col-md-3 col-sm-6 col-xs-12"
              @keyup.enter="handleSearch"
            >
              <template v-slot:prepend>
                <q-icon name="groups" />
              </template>
            </q-select>

            <q-select
              v-model="searchState.form.status"
              label="状态"
              :options="statusOptions"
              outlined
              dense
              clearable
              emit-value
              map-options
              class="col-md-3 col-sm-6 col-xs-12"
              @keyup.enter="handleSearch"
            >
              <template v-slot:prepend>
                <q-icon name="toggle_on" />
              </template>
            </q-select>

            <q-input
              v-model.trim="searchState.form.email"
              label="邮箱"
              outlined
              dense
              clearable
              class="col-md-3 col-sm-6 col-xs-12"
              @keyup.enter="handleSearch"
            >
              <template v-slot:prepend>
                <q-icon name="email" />
              </template>
            </q-input>

            <q-input
              v-model.trim="searchState.form.mobile"
              label="手机号"
              outlined
              dense
              clearable
              class="col-md-3 col-sm-6 col-xs-12"
              @keyup.enter="handleSearch"
            >
              <template v-slot:prepend>
                <q-icon name="mobile" />
              </template>
            </q-input>

            <div class="col-md-3 col-sm-6 col-xs-12">
              <DateRangePicker />
            </div>

            <!-- 操作按钮 -->
            <div class="col-md-3 col-sm-6 col-xs-12 flex items-center">
              <q-btn
                type="submit"
                color="primary"
                :label="$q.screen.gt.xs ? '查询' : ''"
                icon="search"
                :class="$q.screen.gt.xs ? 'q-mr-sm' : 'q-mr-xs'"
                :loading="searchState.loading"
                :dense="$q.screen.lt.md"
              />
              <q-btn
                @click="resetSearch"
                :label="$q.screen.gt.xs ? '重置' : ''"
                outline
                color="primary"
                icon="refresh"
                :class="$q.screen.gt.xs ? 'q-mr-sm' : 'q-mr-xs'"
                :dense="$q.screen.lt.md"
              />
            </div>
          </q-form>
        </q-card-section>
      </q-slide-transition>
    </q-card>

    <!-- 操作按钮和表格 -->
    <q-card flat bordered>
      <q-card-section class="row items-center bg-grey-2">
        <!-- 左侧：操作按钮 -->
        <div class="col-auto q-gutter-x-sm">
          <q-btn
            color="primary"
            :label="$q.screen.gt.xs ? '新增用户' : ''"
            icon="add"
            @click="showAddDialog"
            :loading="searchState.loading"
            dense
          />
          <q-btn
            color="negative"
            :label="$q.screen.gt.xs ? '批量删除' : ''"
            icon="delete"
            :disable="searchState.selected.length === 0"
            @click="confirmBatchDelete"
            :loading="searchState.loading"
            dense
          />
          <q-btn
            color="grey"
            :label="$q.screen.gt.xs ? '导出数据' : ''"
            icon="file_download"
            @click="exportData"
            :loading="exportLoading"
            dense
          />
        </div>

        <!-- 右侧：表格操作按钮 -->
        <q-space />
        <div class="col-auto q-gutter-x-xs">
          <q-btn
            round
            dense
            flat
            :icon="showSearchInput ? 'search_off' : 'search'"
            @click="toggleSearchInput"
          >
            <q-tooltip>{{ showSearchInput ? '隐藏搜索' : '显示搜索' }}</q-tooltip>
          </q-btn>
          <q-btn round dense flat icon="refresh" @click="refreshTable">
            <q-tooltip>刷新</q-tooltip>
          </q-btn>
          <q-btn round dense flat icon="view_column" @click="showColumnSelector">
            <q-tooltip>显隐列</q-tooltip>
          </q-btn>
        </div>
      </q-card-section>

      <!-- 数据表格 -->
      <q-table
        v-model:selected="searchState.selected"
        :rows="users"
        :columns="visibleColumns"
        row-key="id"
        :loading="searchState.loading"
        :pagination="searchState.pagination"
        @request="onRequest"
        binary-state-sort
        flat
        bordered
        selection="multiple"
        :rows-per-page-options="[10, 20, 50, 100]"
      >
        <!-- 序号列自定义 -->
        <template v-slot:body-cell-index="props">
          <q-td :props="props">
            {{ props.row.index }}
          </q-td>
        </template>

        <!-- 部门列自定义 -->
        <template v-slot:body-cell-dept="props">
          <q-td :props="props">
            {{ props.row.dept?.label || '-' }}
          </q-td>
        </template>

        <!-- 状态列自定义 -->
        <template v-slot:body-cell-status="props">
          <q-td :props="props">
            <q-badge :color="props.row.status ? 'positive' : 'negative'">
              {{ props.row.status ? '启用' : '禁用' }}
            </q-badge>
          </q-td>
        </template>

        <!-- 操作列 -->
        <template v-slot:body-cell-actions="props">
          <q-td :props="props" class="q-gutter-x-xs">
            <q-btn
              dense
              color="primary"
              icon="edit"
              @click="showEditDialog(props.row)"
              :loading="props.row.id === currentUserId && searchState.loading"
            >
              <q-tooltip>编辑</q-tooltip>
            </q-btn>
            <q-btn
              dense
              :color="props.row.status ? 'negative' : 'positive'"
              :icon="props.row.status ? 'toggle_off' : 'toggle_on'"
              @click="toggleStatus(props.row)"
              :loading="props.row.id === currentUserId && searchState.loading"
            >
              <q-tooltip>{{ props.row.status ? '禁用' : '启用' }}</q-tooltip>
            </q-btn>
            <q-btn
              dense
              color="secondary"
              icon="vpn_key"
              @click="showResetPwdDialog(props.row)"
              :loading="props.row.id === currentUserId && searchState.loading"
            >
              <q-tooltip>重置密码</q-tooltip>
            </q-btn>
            <q-btn
              dense
              color="orange"
              icon="people"
              @click="showAssignRoleDialog(props.row)"
              :loading="props.row.id === currentUserId && searchState.loading"
            >
              <q-tooltip>分配角色</q-tooltip>
            </q-btn>
            <q-btn
              dense
              color="negative"
              icon="delete"
              @click="confirmDelete(props.row.id)"
              :loading="props.row.id === currentUserId && searchState.loading"
            >
              <q-tooltip>删除</q-tooltip>
            </q-btn>
          </q-td>
        </template>
      </q-table>
    </q-card>

    <!-- 新增/编辑对话框 -->
    <CreateOrUpdateUserDialog
      v-model="dialogVisible"
      :is-edit="isEdit"
      :user-data="userForm"
      :dept-options="deptOptions"
      :role-options="roleOptions"
      @submit="handleFormSubmit"
      @cancel="dialogVisible = false"
    />

    <!-- 重置密码对话框 -->
    <ResetPasswordDialog
      v-model="resetPwdDialogVisible"
      :user-id="currentUserId"
      :user-name="currentUserName"
      @submit="handleResetPwd"
      @cancel="resetPwdDialogVisible = false"
    />

    <!-- 分配角色对话框 -->
    <AssignRoleDialog
      v-model="assignRoleDialogVisible"
      :user-id="currentUserId"
      :user-name="currentUserName"
      @submit="handleAssignRole"
      @cancel="assignRoleDialogVisible = false"
    />

    <!-- 列选择器对话框 -->
    <q-dialog v-model="columnSelectorVisible">
      <q-card style="min-width: 300px">
        <q-card-section>
          <div class="text-h6">显示列</div>
        </q-card-section>

        <q-card-section class="q-pt-none">
          <q-list dense>
            <q-item v-for="column in columns" :key="column.name" tag="label">
              <q-item-section>
                <q-item-label>{{ column.label }}</q-item-label>
              </q-item-section>
              <q-item-section avatar>
                <q-toggle v-model="visibleColumnsMap[column.name]" color="primary" />
              </q-item-section>
            </q-item>
          </q-list>
        </q-card-section>

        <q-card-actions align="right">
          <q-btn flat label="取消" color="primary" v-close-popup />
          <q-btn flat label="确定" color="primary" v-close-popup />
        </q-card-actions>
      </q-card>
    </q-dialog>
  </q-page>
</template>

<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
import { debounce } from 'lodash'
import { exportFile } from 'quasar'
import { listDept } from '@/api/sys/dept'
import { listRole } from '@/api/sys/role'
import { listUser, changeUserStatus, delUser } from '@/api/sys/user'
import CreateOrUpdateUserDialog from './components/CreateOrUpdateUserDialog'
import ResetPasswordDialog from './components/ResetPasswordDialog'
import AssignRoleDialog from './components/AssignRoleDialog'

const { proxy } = getCurrentInstance()

// 表格列定义
const columns = [
  {
    name: 'selection',
    align: 'center',
    label: '',
    field: '',
    sortable: false,
  },
  {
    name: 'index',
    label: '序号',
    field: 'index',
    align: 'center',
    sortable: false,
  },
  {
    name: 'username',
    label: '用户名',
    field: 'username',
    align: 'center',
    sortable: true,
  },
  {
    name: 'name',
    label: '昵称',
    field: 'name',
    align: 'center',
    sortable: true,
  },
  {
    name: 'dept',
    label: '部门',
    field: 'dept',
    align: 'center',
  },
  {
    name: 'email',
    label: '邮箱',
    field: 'email',
    align: 'center',
  },
  {
    name: 'mobile',
    label: '手机号',
    field: 'mobile',
    align: 'center',
  },
  {
    name: 'status',
    label: '状态',
    field: 'status',
    align: 'center',
  },
  {
    name: 'create_time',
    label: '创建时间',
    field: 'create_time',
    align: 'center',
    sortable: true,
  },
  {
    name: 'actions',
    label: '操作',
    align: 'center',
  },
]

// 状态选项
const statusOptions = [
  { label: '全部', value: null },
  { label: '启用', value: true },
  { label: '禁用', value: false },
]

// 部门选项
const deptOptions = ref([])
const roleOptions = ref([])
const users = ref([])
const columnSelectorVisible = ref(false)
const showSearchInput = ref(false)

// 列显示控制
const visibleColumnsMap = ref({
  selection: true,
  index: true,
  username: true,
  name: true,
  dept: true,
  email: true,
  mobile: true,
  status: true,
  create_time: true,
  actions: true,
})

// 计算可见列
const visibleColumns = computed(() => {
  return columns.filter((column) => visibleColumnsMap.value[column.name])
})

// 状态管理
const searchState = reactive({
  form: {
    username: '',
    name: '',
    deptId: null,
    status: null,
    email: '',
    mobile: '',
    createTimeRange: null,
  },
  pagination: {
    page: 1,
    rowsPerPage: 10,
    rowsNumber: 0,
    sortBy: 'create_time',
    descending: true,
  },
  loading: false,
  selected: [],
})

// 对话框相关
const dialogVisible = ref(false)
const resetPwdDialogVisible = ref(false)
const assignRoleDialogVisible = ref(false)
const isEdit = ref(false)
const exportLoading = ref(false)
const userForm = ref({
  id: null,
  username: '',
  name: '',
  email: '',
  mobile: '',
  status: true,
  deptId: null,
  roleIds: [],
})
const currentUserId = ref(null)
const currentUserName = ref('')

// 初始化加载数据
onMounted(() => {
  Promise.all([loadDeptOptions(), loadRoleOptions()])
    .then(() => {
      onRequest({
        pagination: searchState.pagination,
        filter: searchState.form,
      })
    })
    .catch((error) => {
      console.error(' 初始化失败:', error)
      proxy.$q.notify({
        type: 'negative',
        message: '初始化失败',
        caption: error.message,
      })
    })
})

// 加载部门选项
async function loadDeptOptions() {
  try {
    const res = await listDept()
    deptOptions.value = [
      { label: '全部', value: null },
      ...res.data.map((item) => ({
        label: item.label,
        value: item.value,
      })),
    ]
  } catch (error) {
    console.error(' 加载部门选项失败:', error)
    proxy.$q.notify({
      type: 'negative',
      message: '加载部门选项失败',
      caption: error.message,
    })
    throw error
  }
}

// 加载角色选项
async function loadRoleOptions() {
  try {
    const res = await listRole()
    roleOptions.value = res.data
  } catch (error) {
    console.error(' 加载角色选项失败:', error)
    proxy.$q.notify({
      type: 'negative',
      message: '加载角色选项失败',
      caption: error.message,
    })
    throw error
  }
}

// 表格请求方法
const onRequest = async (props) => {
  const { page, rowsPerPage, sortBy, descending } = props.pagination
  searchState.loading = true

  try {
    // 处理时间范围参数
    const timeRange = searchState.form.createTimeRange
    const params = {
      pageNum: page,
      pageSize: rowsPerPage,
      orderBy: sortBy,
      orderType: descending ? 'desc' : 'asc',
      ...Object.fromEntries(
        Object.entries(searchState.form).filter(([key, value]) => {
          if (key === 'createTimeRange') return false
          return value !== null && value !== '' && value !== undefined
        }),
      ),
    }

    // 添加时间范围条件
    if (timeRange && timeRange.from && timeRange.to) {
      params.createTimeStart = timeRange.from
      params.createTimeEnd = timeRange.to
    }

    const res = await listUser(params)

    // 添加序号字段
    users.value = res.data.map((item, index) => ({
      ...item,
      index: (page - 1) * rowsPerPage + index + 1,
    }))

    // 更新分页信息
    searchState.pagination = {
      ...searchState.pagination,
      page,
      rowsPerPage,
      rowsNumber: res.data.total,
      sortBy,
      descending,
    }
  } catch (error) {
    proxy.$q.notify({
      type: 'negative',
      message: '加载用户列表失败',
      caption: error.message || '请检查网络连接',
    })
  } finally {
    searchState.loading = false
  }
}

// 查询处理 - 添加防抖
const handleSearch = debounce(() => {
  searchState.pagination.page = 1
  onRequest({
    pagination: searchState.pagination,
    filter: searchState.form,
  })
}, 300)

// 刷新表格
const refreshTable = () => {
  onRequest({
    pagination: searchState.pagination,
    filter: searchState.form,
  })
}

// 显示列选择器
const showColumnSelector = () => {
  columnSelectorVisible.value = true
}

// 重置查询
const resetSearch = () => {
  searchState.form = {
    username: '',
    name: '',
    deptId: null,
    status: null,
    email: '',
    mobile: '',
    createTimeRange: null,
  }
  searchState.selected = []
  handleSearch()
}

// 切换搜索输入框显示
const toggleSearchInput = () => {
  showSearchInput.value = !showSearchInput.value
}

// 导出数据
const exportData = async () => {
  exportLoading.value = true
  try {
    const params = {
      ...Object.fromEntries(
        Object.entries(searchState.form).filter(([key, value]) => {
          if (key === 'createTimeRange') return false
          return value !== null && value !== '' && value !== undefined
        }),
      ),
    }

    // 处理时间范围
    if (searchState.form.createTimeRange?.from && searchState.form.createTimeRange?.to) {
      params.createTimeStart = searchState.form.createTimeRange.from
      params.createTimeEnd = searchState.form.createTimeRange.to
    }

    proxy.$q.notify({
      type: 'positive',
      message: '导出成功',
    })
  } catch (error) {
    proxy.$q.notify({
      type: 'negative',
      message: '导出失败',
      caption: error.message,
    })
  } finally {
    exportLoading.value = false
  }
}

// 显示新增对话框
function showAddDialog() {
  isEdit.value = false
  userForm.value = {
    id: null,
    username: '',
    name: '',
    email: '',
    mobile: '',
    status: true,
    deptId: null,
    roleIds: [],
  }
  dialogVisible.value = true
}

// 显示编辑对话框
function showEditDialog(row) {
  isEdit.value = true
  currentUserId.value = row.id
  userForm.value = {
    id: row.id,
    username: row.username,
    name: row.name,
    email: row.email,
    mobile: row.mobile,
    status: row.status,
    deptId: row.dept?.value || null,
    roleIds: row.roleIds || [],
  }
  dialogVisible.value = true
}

// 处理表单提交
function handleFormSubmit() {
  dialogVisible.value = false
  currentUserId.value = null
  onRequest({
    pagination: searchState.pagination,
    filter: searchState.form,
  })
}

// 显示重置密码对话框
function showResetPwdDialog(row) {
  currentUserId.value = row.id
  currentUserName.value = row.username
  resetPwdDialogVisible.value = true
}

// 处理重置密码
function handleResetPwd() {
  resetPwdDialogVisible.value = false
  currentUserId.value = null
  proxy.$q.notify({
    type: 'positive',
    message: '密码重置成功',
  })
}

// 显示分配角色对话框
function showAssignRoleDialog(row) {
  currentUserId.value = row.id
  currentUserName.value = row.username
  assignRoleDialogVisible.value = true
}

// 处理分配角色
function handleAssignRole() {
  assignRoleDialogVisible.value = false
  currentUserId.value = null
  proxy.$q.notify({
    type: 'positive',
    message: '角色分配成功',
  })
}

// 切换状态
async function toggleStatus(row) {
  const action = row.status ? '禁用' : '启用'

  proxy.$q
    .dialog({
      title: '操作确认',
      message: `确定要${action}用户 ${row.username}  吗？`,
      cancel: {
        label: '取消',
        flat: true,
        color: 'grey',
      },
      ok: {
        label: '确认',
        flat: true,
        color: 'primary',
      },
      persistent: true,
    })
    .onOk(async () => {
      currentUserId.value = row.id
      searchState.loading = true

      try {
        await changeUserStatus(row.id, row.status ? 0 : 1)
        row.status = !row.status

        proxy.$q.notify({
          type: 'positive',
          message: `用户已${row.status ? '启用' : '禁用'}`,
          position: 'top',
        })
      } catch (error) {
        proxy.$q.notify({
          type: 'negative',
          message: `${action}用户失败`,
          caption: error.message,
          position: 'top',
        })
      } finally {
        currentUserId.value = null
        searchState.loading = false
      }
    })
}

// 确认删除
function confirmDelete(id) {
  proxy.$q
    .dialog({
      title: '删除确认',
      message: '确定要删除该用户吗？此操作不可恢复！',
      cancel: {
        label: '取消',
        flat: true,
        color: 'grey-7',
      },
      ok: {
        label: '确定删除',
        flat: true,
        color: 'negative',
      },
      persistent: true,
    })
    .onOk(async () => {
      currentUserId.value = id
      searchState.loading = true
      try {
        await delUser(id)
        proxy.$q.notify({
          type: 'positive',
          message: '用户删除成功',
          position: 'top',
          timeout: 2000,
        })
        onRequest({
          pagination: searchState.pagination,
          filter: searchState.form,
        })
      } catch (error) {
        proxy.$q.notify({
          type: 'negative',
          message: '用户删除失败',
          caption: error.message,
          position: 'top',
          timeout: 2000,
        })
      } finally {
        currentUserId.value = null
        searchState.loading = false
      }
    })
}

// 确认批量删除
function confirmBatchDelete() {
  if (searchState.selected.length === 0) {
    proxy.$q.notify({
      type: 'warning',
      message: '请先选择要删除的用户',
      position: 'top',
      timeout: 2000,
    })
    return
  }

  proxy.$q
    .dialog({
      title: '批量删除确认',
      message: `确定要删除选中的 ${searchState.selected.length}  个用户吗？此操作不可恢复！`,
      cancel: {
        label: '取消',
        flat: true,
        color: 'grey-7',
      },
      ok: {
        label: '确认删除',
        flat: true,
        color: 'negative',
      },
      persistent: true,
    })
    .onOk(async () => {
      searchState.loading = true
      try {
        const ids = searchState.selected.map((user) => user.id)
        await delUser(ids)
        proxy.$q.notify({
          type: 'positive',
          message: `成功删除 ${searchState.selected.length}  个用户`,
          position: 'top',
          timeout: 2000,
        })
        searchState.selected = []
        onRequest({
          pagination: searchState.pagination,
          filter: searchState.form,
        })
      } catch (error) {
        proxy.$q.notify({
          type: 'negative',
          message: '批量删除失败',
          caption: error.message,
          position: 'top',
          timeout: 2000,
        })
      } finally {
        searchState.loading = false
      }
    })
}
</script>
